package besta.moon.sql.expression;

import besta.moon.engine.table.Column;
import besta.moon.sql.Expression;
import besta.moon.engine.View;
import besta.moon.engine.selector.DataSource;
import besta.moon.sql.datatype.MutableNumeric;
import besta.moon.sql.parser.SQLTokenizer;

public class ExpressionName extends Expression {

    private String tableAlias;
    private DataSource fromEntry;
    private int colIdx;
    private View table;
    private Column column;

    public ExpressionName(String name) {
        super(NAME);
        setName(name);
    }

    public ExpressionName(int type) {
        super(type);

    }

    public void setNameAfterTableAlias(String name) {
        tableAlias = getName();
        setName(name);
    }

    @Override
    public boolean equals(Object expr) {
        if (!super.equals(expr)) {
            return false;
        }
        if (!(expr instanceof ExpressionName)) {
            return false;
        }
        if (((ExpressionName) expr).fromEntry != fromEntry) {
            return false;
        }
        return true;
    }

    @Override
    public boolean isNull() throws Exception {
        return fromEntry.isNull(colIdx);
    }

    @Override
    public boolean getBoolean() throws Exception {
        return fromEntry.getBoolean(colIdx);
    }

    @Override
    public int getInt() throws Exception {
        return fromEntry.getInt(colIdx);
    }

    @Override
    public long getLong() throws Exception {
        return fromEntry.getLong(colIdx);
    }

    @Override
    public float getFloat() throws Exception {
        return fromEntry.getFloat(colIdx);
    }

    @Override
    public double getDouble() throws Exception {
        return fromEntry.getDouble(colIdx);
    }

    @Override
    public long getMoney() throws Exception {
        return fromEntry.getMoney(colIdx);
    }

    @Override
    public MutableNumeric getNumeric() throws Exception {
        return fromEntry.getNumeric(colIdx);
    }

    @Override
    public Object getObject() throws Exception {
        return fromEntry.getObject(colIdx);
    }

    @Override
    public String getString() throws Exception {
        return fromEntry.getString(colIdx);
    }

    @Override
    public byte[] getBytes() throws Exception {
        return fromEntry.getBytes(colIdx);
    }

    @Override
    public int getDataType() {
        switch (getType()) {
            case NAME:
            case GROUP_BY:
                return fromEntry.getDataType(colIdx);
            case FIRST:
            case LAST:
            case MAX:
            case MIN:
            case SUM:
                return getParams()[0].getDataType();
            case COUNT:
                return SQLTokenizer.INT;
            default:
                throw new Error();
        }
    }

    public void setFrom(DataSource fromEntry, int colIdx, View table) {
        this.fromEntry = fromEntry;
        this.colIdx = colIdx;
        this.table = table;
        this.column = table.columns.get(colIdx);
    }

    public void setFrom(DataSource fromEntry, int colIdx, Column column) {
        this.fromEntry = fromEntry;
        this.colIdx = colIdx;
        this.column = column;
    }

    public DataSource getDataSource() {
        return fromEntry;
    }

    public String getTableAlias() {
        return tableAlias;
    }

    public final View getTable() {
        return table;
    }

    public final int getColumnIndex() {
        return colIdx;
    }

    public final Column getColumn() {
        return column;
    }

    @Override
    final public String toString() {
        if (tableAlias == null) {
            return String.valueOf(getAlias());
        }
        return tableAlias + "." + getAlias();
    }

    @Override
    public String getTableName() {
        if (table != null) {
            return table.getName();
        }
        return null;
    }

    @Override
    public int getPrecision() {
        return column.getPrecision();
    }

    @Override
    public int getScale() {
        return column.getScale();
    }

    @Override
    public int getDisplaySize() {
        return column.getDisplaySize();
    }

    @Override
    public boolean isAutoIncrement() {
        return column.isAutoIncrement();
    }

    @Override
    public boolean isCaseSensitive() {
        return column.isCaseSensitive();
    }

    @Override
    public boolean isNullable() {
        return column.isNullable();
    }

    @Override
    public boolean isDefinitelyWritable() {
        return true;
    }

}
